home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / os2 / remin301.zip / REMIN300.ZIP / QUEUE.C < prev    next >
C/C++ Source or Header  |  1992-11-10  |  10KB  |  304 lines

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  QUEUE.C                                                    */
  4. /*                                                             */
  5. /*  Queue up reminders for subsequent execution.               */
  6. /*                                                             */
  7. /*  This file is part of REMIND.                               */
  8. /*  Copyright (C) 1992 by David F. Skoll.                      */
  9. /*                                                             */
  10. /***************************************************************/
  11. #include <stdio.h>
  12. #include <signal.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include "config.h"
  16. #ifdef HAVE_STDLIB_H
  17. #include <stdlib.h>
  18. #endif
  19. #ifdef HAVE_MALLOC_H
  20. #include <malloc.h>
  21. #endif
  22. #include "globals.h"
  23. #include "err.h"
  24. #include "types.h"
  25. #include "protos.h"
  26.  
  27. /* List structure for holding queued reminders */
  28. typedef struct _queuedrem {
  29.    struct _queuedrem *next;
  30.    int typ;
  31.    int RunDisabled;
  32.    char *text;
  33.    TimeTrig tt;
  34. } QueuedRem;
  35.  
  36. /* Global variables */
  37.  
  38. static QueuedRem *QueueHead;
  39. static time_t FileModTime;
  40. static struct stat StatBuf;
  41.  
  42. PRIVATE void CheckInitialFile ARGS ((void));
  43. PRIVATE int CalculateNextTime ARGS ((QueuedRem *q));
  44. PRIVATE QueuedRem *FindNextReminder ARGS ((void));
  45. PRIVATE void SigIntHandler ARGS ((void));
  46.  
  47. /***************************************************************/
  48. /*                                                             */
  49. /*  QueueReminder                                              */
  50. /*                                                             */
  51. /*  Put the reminder on a queue for later, if queueing is      */
  52. /*  enabled.                                                   */
  53. /*                                                             */
  54. /***************************************************************/
  55. #ifdef HAVE_PROTOS
  56. PUBLIC int QueueReminder(ParsePtr p, int typ, TimeTrig *tim)
  57. #else
  58. int QueueReminder(p, typ, tim)
  59. ParsePtr p;
  60. int typ;
  61. TimeTrig *tim;
  62. #endif
  63. {
  64.    QueuedRem *qelem;
  65.  
  66.    if (DontQueue ||
  67.        tim->ttime == NO_TIME ||
  68.        typ == CAL_TYPE ||
  69.        tim->ttime < SystemTime() / 60 ||
  70.        ((typ == RUN_TYPE) && RunDisabled)) return OK;
  71.  
  72.    qelem = NEW(QueuedRem);
  73.    if (!qelem) {
  74.       Eprint("No memory to queue reminder.");
  75.       return E_NO_MEM;
  76.    }
  77.    qelem->text = StrDup(p->pos);  /* Guaranteed that parser is not nested. */
  78.    if (!qelem->text) {
  79.       free(qelem);
  80.       Eprint("No memory to queue reminder.");
  81.       return E_NO_MEM;
  82.    }
  83.    qelem->typ = typ;
  84.    qelem->tt = *tim;
  85.    qelem->next = QueueHead;
  86.    qelem->RunDisabled = RunDisabled;
  87.    QueueHead = qelem;
  88.    NumQueued++;
  89.    return OK;
  90. }
  91.  
  92. /***************************************************************/
  93. /*                                                             */
  94. /*  HandleQueuedReminders                                      */
  95. /*                                                             */
  96. /*  Handle the issuing of queued reminders in the background   */
  97. /*                                                             */
  98. /***************************************************************/
  99. #ifdef HAVE_PROTOS
  100. PUBLIC void HandleQueuedReminders(void)
  101. #else
  102. void HandleQueuedReminders()
  103. #endif
  104. {
  105.    QueuedRem *q = QueueHead;
  106.    long TimeToSleep;
  107.    unsigned SleepTime;
  108.    Parser p;
  109.    Trigger trig;
  110.  
  111.    /* Suppress the BANNER from being issued */
  112.    NumTriggered = 1;
  113.    
  114.    /* If we are not connected to a tty, then we must close the
  115.     * standard file descriptors. This is to prevent someone
  116.     * doing:
  117.     *        remind file | <filter> | >log
  118.     * and have <filter> hung because the child (us) is still
  119.     * connected to it. This means the only commands that will be
  120.     * processed correctly are RUN commands, provided they mail
  121.     * the result back or use their own resource (as a window).
  122.     */
  123.    if (!DontFork && (!isatty(1) || !isatty(2))) {
  124.       close(1);
  125.       close(2);
  126.    }
  127.  
  128.    /* If we're a daemon, get the mod time of initial file */
  129.    if (Daemon) {
  130.       if (stat(InitialFile, &StatBuf)) {
  131.          fprintf(ErrFp, "Cannot stat %s - not running as daemon!\n",
  132.                       InitialFile);
  133.          Daemon = 0;
  134.       } else FileModTime = StatBuf.st_mtime;
  135.    }
  136.    
  137.    /* Initialize the queue - initialize all the entries time of issue */
  138.    
  139.    while (q) {
  140.       q->tt.nexttime = (int) (SystemTime()/60 - 1);
  141.       q->tt.nexttime = CalculateNextTime(q);
  142.       q = q->next;
  143.    }
  144.  
  145.    if (!DontFork || Daemon) signal(SIGINT, SigIntHandler);
  146.  
  147.    /* Sit in a loop, issuing reminders when necessary */
  148.    while(1) {
  149.       q = FindNextReminder();
  150.  
  151.       /* If no more reminders to issue, we're unless we're a daemon. */
  152.       if (!q && !Daemon) exit(0);
  153.  
  154.       if (Daemon && !q)
  155.          TimeToSleep = (long) 60*Daemon;
  156.       else
  157.          TimeToSleep = (long) q->tt.nexttime * 60L - SystemTime();
  158.  
  159.       while (TimeToSleep > 0L) {
  160.          SleepTime = (unsigned) ((TimeToSleep > 30000L) ? 30000 : TimeToSleep);
  161.  
  162.      if (Daemon && SleepTime > 60*Daemon) SleepTime = 60*Daemon;
  163.  
  164.      sleep(SleepTime);
  165.  
  166.      if (Daemon && SleepTime) CheckInitialFile();
  167.  
  168.      if (Daemon && !q)
  169.         TimeToSleep = (long) 60*Daemon;
  170.          else
  171.         TimeToSleep = (long) q->tt.nexttime * 60L - SystemTime();
  172.       }
  173.  
  174.       /* Trigger the reminder */
  175.       CreateParser(q->text, &p);
  176.       trig.typ = q->typ;
  177.       (void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
  178.       fflush(stdout);
  179.       
  180.       /* Calculate the next trigger time */
  181.       q->tt.nexttime = CalculateNextTime(q);
  182.    }
  183. }
  184.    
  185.  
  186. /***************************************************************/
  187. /*                                                             */
  188. /*  CalculateNextTime                                          */
  189. /*                                                             */
  190. /*  Calculate the next time when a reminder should be issued.  */
  191. /*  Return NO_TIME if reminder expired.                        */
  192. /*                                                             */
  193. /***************************************************************/
  194. #ifdef HAVE_PROTOS
  195. PRIVATE int CalculateNextTime(QueuedRem *q)
  196. #else
  197. static int CalculateNextTime(q)
  198. QueuedRem *q;
  199. #endif
  200. {
  201.    int tim = q->tt.ttime;
  202.    int rep = q->tt.rep;
  203.    int delta = q->tt.delta;
  204.    int curtime = q->tt.nexttime+1;
  205.  
  206.    if (delta == NO_DELTA)
  207.       if (tim < curtime) return NO_TIME; else return tim;
  208.  
  209.    tim -= delta;
  210.    if (rep == NO_REP) rep = delta;
  211.    if (tim < curtime) tim += ((curtime - tim) / rep) * rep;
  212.    if (tim < curtime) tim += rep;
  213.    if (tim > q->tt.ttime) tim = q->tt.ttime;
  214.    if (tim < curtime) return NO_TIME; else return tim;
  215. }
  216.  
  217. /***************************************************************/
  218. /*                                                             */
  219. /*  FindNextReminder                                           */
  220. /*                                                             */
  221. /*  Find the next reminder to trigger                          */
  222. /*                                                             */
  223. /***************************************************************/
  224. #ifdef HAVE_PROTOS
  225. PRIVATE QueuedRem *FindNextReminder(void)
  226. #else
  227. static QueuedRem *FindNextReminder()
  228. #endif
  229. {
  230.    QueuedRem *q = QueueHead;
  231.    QueuedRem *ans = NULL;
  232.  
  233.    while (q) {
  234.       if (q->tt.nexttime != NO_TIME) {
  235.          if (!ans) ans = q;
  236.      else if (q->tt.nexttime < ans->tt.nexttime) ans = q;
  237.        }
  238.       
  239.       q = q->next;
  240.    }
  241.    return ans;
  242. }
  243.    
  244.  
  245. /***************************************************************/
  246. /*                                                             */
  247. /* SigIntHandler                                               */
  248. /*                                                             */
  249. /* For debugging purposes, when sent a SIGINT, we print the    */
  250. /* contents of the queue.  This does NOT work when the -f      */
  251. /* command-line flag is supplied.                              */
  252. /*                                                             */
  253. /***************************************************************/
  254. #ifdef HAVE_PROTOS
  255. PRIVATE void SigIntHandler(void)
  256. #else
  257. static void SigIntHandler()
  258. #endif
  259. {
  260.    QueuedRem *q = QueueHead;
  261.  
  262. #ifdef SYSV
  263.    signal(SIGINT, SigIntHandler);
  264. #endif
  265.  
  266.    printf("Contents of AT queue:%s", NL);
  267.  
  268.    while (q) {
  269.       printf("Trigger: %02d:%02d  Activate: %02d:%02d  Rep: %d  Delta: %d%s",
  270.               q->tt.ttime / 60, q->tt.ttime % 60,
  271.           q->tt.nexttime / 60, q->tt.nexttime % 60,
  272.               q->tt.rep, q->tt.delta, NL);
  273.       printf("Text: %s %s%s%s", ((q->typ == MSG_TYPE) ? "MSG" : "RUN"),
  274.               q->text,
  275.               NL, NL);
  276.       q = q->next;
  277.    }
  278.    printf(NL);
  279. }
  280. /***************************************************************/
  281. /*                                                             */
  282. /*  CheckInitialFile                                           */
  283. /*                                                             */
  284. /*  If the initial file has been modified, then restart the    */
  285. /*  daemon.                                                    */
  286. /*                                                             */
  287. /***************************************************************/
  288. #ifdef HAVE_PROTOS
  289. PRIVATE void CheckInitialFile(void)
  290. #else
  291. static void CheckInitialFile()
  292. #endif
  293. {
  294.    /* If date has rolled around, or file has changed, spawn a new version. */
  295.    time_t tim = FileModTime;
  296.    int y, m, d;
  297.  
  298.    if (stat(InitialFile, &StatBuf) == 0) tim = StatBuf.st_mtime;
  299.    if (tim != FileModTime ||
  300.        RealToday != SystemDate(&y, &m, &d))
  301.           execvp(ArgV[0], ArgV);
  302. }
  303.  
  304.